#include "include.h"

#if I2S_EN
//          IIS_IO_GPIOA    IIS_IO_GPIOE
//DI  :     PA0             PE0
//DO  :     PA1             PE1
//BCLK:     PA2             PE2
//LRCLK:    PA3             PE3
//MCLK:     PA4             PE4

#define I2S_DMA_BUF_LEN         512
#define I2S_DMA_BUF_INDEX       5
typedef struct {
    volatile u8 wptr;
    volatile u8 rptr;
    volatile u8 len;
    u16 dma_cnt;
    u32 dma_in0;
    u32 dma_in1;
    u32 dma_out0;
    u32 dma_out1;
    u8 (*buf)[I2S_DMA_BUF_LEN];
}i2s_dma_t;

typedef struct {
    u8 mapping      : 1;
    u8 mode         : 1;
    u8 bit_mode     : 1;
    u8 data_mode    : 1;
    u8 dma_en       : 1;
    u8 mclk_en      : 1;
    u8 mclk_sel     : 2;
    u8 pcm_mode_en  : 1;
	u8 spr          : 1;       //slave输入的采样率
	u8 mode_ext		: 1;
    i2s_dma_t i2s_dma;
}i2s_cfg_t;
u8 tbl_i2s_32bit_clk[3][2] = {
    {1-1, 8-1}, //64fs
    {4-1, 2-1}, //128fs
    {2-1, 4-1}, //256fs
};
u8 tbl_i2s_16bit_clk[3][2] = {
    {8-1, 2-1}, //64fs
    {4-1, 4-1}, //128fs
    {2-1, 8-1}, //256fs
};
i2s_cfg_t bsp_i2s_cfg;
void i2s_init(void *cfg);
void i2s_exit(void);
void i2s_set_sample(u8 (*i2s_32bit_tb)[2],u8 (*i2s_16bit_tb)[2]);
void iis2bt_sco_sync_init(void);
void bsp_i2s_init(void)
{
    bsp_i2s_cfg.mapping     = I2S_MAPPING_SEL;
    #if IISMS_IOCHECK
    bsp_i2s_cfg.mode        = iis_gpiox_2_gnd_check();
    #else
    bsp_i2s_cfg.mode        = I2S_MODE_SEL;
    #endif // IISMS_IOCHECK
    bsp_i2s_cfg.bit_mode    = I2S_BIT_MODE;
    bsp_i2s_cfg.data_mode   = I2S_DATA_MODE;
    bsp_i2s_cfg.dma_en      = I2S_DMA_EN;
    bsp_i2s_cfg.mclk_en     = I2S_MCLK_EN;
    bsp_i2s_cfg.mclk_sel    = I2S_MCLK_SEL;
    bsp_i2s_cfg.pcm_mode_en = I2S_PCM_MODE;
    bsp_i2s_cfg.spr         = DAC_OUT_SPR;
    bsp_i2s_cfg.mode_ext    = 0;
    i2s_init(&bsp_i2s_cfg);
    i2s_set_sample(tbl_i2s_32bit_clk,tbl_i2s_16bit_clk);
    #if DMA_OUT_I2S_SEL == I2S_DMA_BT && I2S_EN
    iis2bt_sco_sync_init();
    #endif

    if (bsp_i2s_cfg.dma_en) {
        DACDIGCON0 &= ~BIT(23);
    } else {
        CLKCON0 |= BIT(0);                  //enable RC
        CLKCON0 = (CLKCON0 & ~(0x3 << 2));  //system clk select RC
        DACDIGCON0 |= BIT(23);
        delay_us(3);
        CLKCON0 = (CLKCON0 | (0x2 << 2));  //system clk select 26M
	}
}

void bsp_i2s_exit(void)
{
    i2s_exit();
}
AT(.com_text.i2s)
u8 iis_dat_dir(void)
{
    return I2S_DATA_DIR;
}
AT(.com_text.i2s)
u8 dma_in_i2s_sel(void)
{
    return DMA_IN_I2S_SEL;
}
AT(.com_text.i2s)
u8 dma_out_i2s_sel(void)
{
    return DMA_OUT_I2S_SEL;
}
#if IISMS_IOCHECK
AT(.text.bsp.sys.init)
bool iis_gpiox_2_gnd_check(void)  //iis 特定GPIO 接地为从机
{
    u8 i,cnt;
    bool res = false;
    gpio_t tws_sel_left_gpio;
    gpio_t *g = &tws_sel_left_gpio;
    u8 io_num = IISMS_IOCHECK;
    //printf("io_num = %d\n",io_num);
    if ((!io_num) || (io_num > IO_PG0)) {
        return false;
    }
    bsp_gpio_cfg_init(&tws_sel_left_gpio, IISMS_IOCHECK);
    //io sta backup
    u32 bk_de = g->sfr[GPIOxDE];
    u32 bk_pu = g->sfr[GPIOxPU];
    u32 bk_dir = g->sfr[GPIOxDIR];
    //数字IO, 开上拉.
    g->sfr[GPIOxDE] |= BIT(g->num);
    g->sfr[GPIOxPU] |= BIT(g->num);
    g->sfr[GPIOxDIR] |= BIT(g->num);

    i = 6;
    cnt = 0;
    while(i--) {
        delay_ms(5);
        if (!(g->sfr[GPIOx] & BIT(g->num)) ) {   //to GND
            //printf("GND\n");
            cnt++;
        } else {
            //printf("!!!PU\n");
        }
        if (cnt >= 3) {
            res = true;
            break;
        }
    }
    //检测完成, 恢复以前IO状态
    g->sfr[GPIOxDE] =  bk_de;
    g->sfr[GPIOxPU] =  bk_pu;
    g->sfr[GPIOxDIR] = bk_dir;
    //printf("res = %d,i = %d, cnt = %d\n",res,i,cnt);
    return res;
}
#endif // IISMS_IOCHECK
#endif
